//===----------------------------------------------------------------------===//
//
//                         CMU-DB Project (15-445/645)
//                         ***DO NO SHARE PUBLICLY***
//
// Identification: src/page/b_plus_tree_leaf_page.cpp
//
// Copyright (c) 2018, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <sstream>

#include "common/exception.h"
#include "common/rid.h"
#include "storage/page/b_plus_tree_leaf_page.h"

namespace bustub {

/*****************************************************************************
 * HELPER METHODS AND UTILITIES
 *****************************************************************************/

/**
 * Init method after creating a new leaf page
 * Including set page type, set current size to zero, set page id/parent id, set
 * next page id and set max size
 */
INDEX_TEMPLATE_ARGUMENTS
void B_PLUS_TREE_LEAF_PAGE_TYPE::Init(page_id_t page_id, page_id_t parent_id, int max_size) {
  this->SetPageId(page_id);
  this->SetMaxSize(max_size);
  this->SetSize(0);//当前大小为0
  this->SetParentPageId(parent_id);
  this->SetNextPageId(INVALID_PAGE_ID);
  this->SetPageType(IndexPageType::LEAF_PAGE);
}

/**
 * Helper methods to set/get next page id
 */
INDEX_TEMPLATE_ARGUMENTS
auto B_PLUS_TREE_LEAF_PAGE_TYPE::GetNextPageId() const -> page_id_t { 
  return this->next_page_id_;
}

INDEX_TEMPLATE_ARGUMENTS
void B_PLUS_TREE_LEAF_PAGE_TYPE::SetNextPageId(page_id_t next_page_id) {
  this->next_page_id_=next_page_id;
}

/*
 * Helper method to find and return the key associated with input "index"(a.k.a
 * array offset)
 */
INDEX_TEMPLATE_ARGUMENTS
auto B_PLUS_TREE_LEAF_PAGE_TYPE::KeyAt(int index) const -> KeyType {
  // replace with your own code
  KeyType key = this->array_[index].first;
  return key;
}

INDEX_TEMPLATE_ARGUMENTS
auto B_PLUS_TREE_LEAF_PAGE_TYPE::ValueAt(int index) const -> ValueType{
  ValueType value = this->array_[index].second;
  return value;
}
INDEX_TEMPLATE_ARGUMENTS
void B_PLUS_TREE_LEAF_PAGE_TYPE::SetKeyAt(const KeyType& key,int index){
  this->array_[index].first = key;
}
INDEX_TEMPLATE_ARGUMENTS
void B_PLUS_TREE_LEAF_PAGE_TYPE::SetValueAt(const ValueType& value,int index){
  this->array_[index].second = value;
}


INDEX_TEMPLATE_ARGUMENTS
auto B_PLUS_TREE_LEAF_PAGE_TYPE::SearchKey(const KeyType &key, const KeyComparator &comparator) -> int32_t{

  // int start=0,end=this->GetSize(),mid=0;//注意是GetSize 不是GetMaxSize
  int start=0,end=this->GetSize()-1,mid=0;//注意是GetSize 不是GetMaxSize
  while (start<=end)
  {
    mid = (start+end)/2;
    if(comparator(key,this->array_[mid].first)==1){
      start = mid+1;
    }else if(comparator(key,this->array_[mid].first)==-1){
      end = mid-1;
    }else{
      return mid;
    }
  }

  return -1;
}

INDEX_TEMPLATE_ARGUMENTS
void B_PLUS_TREE_LEAF_PAGE_TYPE::CopyToTemp(MappingType*& desc){
  for(int i=0;i<this->GetSize();i++){
    desc[i].first = this->KeyAt(i);
    desc[i].second = this->ValueAt(i);
  }
}

INDEX_TEMPLATE_ARGUMENTS
void B_PLUS_TREE_LEAF_PAGE_TYPE::Erase(){
  memset(this->array_,0,this->GetMaxSize()*sizeof(MappingType));
  this->SetSize(0);
}
INDEX_TEMPLATE_ARGUMENTS
bool B_PLUS_TREE_LEAF_PAGE_TYPE::DeleteKV(const KeyType& key,const KeyComparator &comparator){
  int32_t idx = this->SearchKey(key,comparator);
  if(idx<0){
    std::cout<<"DeleteKV idx < 0"<<std::endl;
    return false;
  }
  // this->array_[idx]=0;
  for(int i=idx;i<this->GetSize()-1;i++){
    this->array_[i]=this->array_[i+1];
  }
  this->SetSize(this->GetSize()-1);
  return true;

}
INDEX_TEMPLATE_ARGUMENTS
void B_PLUS_TREE_LEAF_PAGE_TYPE::SwapVaribales(BPlusTreePage* newPage){
  B_PLUS_TREE_LEAF_PAGE_TYPE* newLeaf = reinterpret_cast<B_PLUS_TREE_LEAF_PAGE_TYPE*>(newPage);
  int tempLen = newPage->GetSize();
  MappingType * tempMemory = new MappingType[tempLen];
  for(int i=0;i<newLeaf->GetSize();i++){
    tempMemory[i] = newLeaf->array_[i];
  }
  newLeaf->Erase();
  for(int i=0;i<this->GetSize();i++){
    newLeaf->array_[i] = this->array_[i];
    newLeaf->IncreaseSize(1);
  }
  for(int i=0;i<tempLen;i++){
    this->array_[i] = tempMemory[i];
    this->IncreaseSize(1);
  }
}

template class BPlusTreeLeafPage<GenericKey<4>, RID, GenericComparator<4>>;
template class BPlusTreeLeafPage<GenericKey<8>, RID, GenericComparator<8>>;
template class BPlusTreeLeafPage<GenericKey<16>, RID, GenericComparator<16>>;
template class BPlusTreeLeafPage<GenericKey<32>, RID, GenericComparator<32>>;
template class BPlusTreeLeafPage<GenericKey<64>, RID, GenericComparator<64>>;
}  // namespace bustub
